home *** CD-ROM | disk | FTP | other *** search
/ START Magazine / START VOL 4 NO 10.st / info_src.arc / SORT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-02-01  |  26.8 KB  |  807 lines

  1. {InfoBaseST by James W. Maki (c) Copyright 1990 by Antic Publishing, Inc.}
  2. {$M+}
  3. {$E+}
  4.  
  5. Program SearchAndSort_Module;
  6.  
  7.       {$I A:GEMSUBS.PAS }
  8.       {$I A:AUXSUBS.PAS }
  9.  
  10.  Const
  11.       {$I B:MOD_CONS.PAS }
  12.  
  13.  Type
  14.       {$I B:MOD_TYPE.PAS }
  15.  
  16.  Var
  17.       {$I B:MOD_VAR.PAS }
  18.  
  19. {  ******************************  External ***************************** }
  20.   procedure GetStr(CurRec : DataPtr ; Var DisplayStr : Str255 ;
  21.                    Start, Size : short_integer ) ;
  22.      External ;
  23.  
  24.   procedure Int_AddARec(Var FirstRec, CurRec, LastRec : IntPtr ; 
  25.                             Value : short_integer ) ;
  26.      External ;
  27.      
  28.   procedure DS_DeleteARec(CurRec : DataPtr) ;
  29.      External ;
  30.  
  31.   procedure DispDataRec( CurRec : DataPtr ) ;
  32.      External ;
  33.      
  34.   procedure DrawRecord(CurRec : DataPtr ) ;
  35.      External ;
  36.  
  37.   procedure LastNameFirst( Var Name : Str255) ;
  38.      External ;
  39.  
  40.   procedure DisposeInt(Var FirstRec, CurRec, LastRec : IntPtr ) ;
  41.      External ;
  42.  
  43.   procedure MinusMemAvail(RecSize : long_integer ) ;
  44.      External ;
  45.  
  46.   procedure ConvDate(    Date : Str255 ; 
  47.                         Var Month, Day, Year : short_integer ) ;
  48.      External ;
  49.  
  50.   procedure ConvDollar( RecStr : Str255 ; Var RecNum : real ) ;
  51.      External ;
  52.  
  53.   procedure CheckNumber(Var NumStr : Str255) ;
  54.      External ;
  55.  
  56.   procedure GetAscii(    Character : StrChar ;
  57.                      Var CharInt : short_integer) ;
  58.      External ;
  59.  
  60.   procedure GetChar(      CurRec  : ScrPtr ; D_CurRec  : DataPtr ; 
  61.                     Var Character : StrChar ; Position  : short_integer ) ;
  62.      External ;
  63.  
  64.   procedure ClrHome ;
  65.      External ;
  66. {  ************************* COMPARE ROUTINES *************************** }
  67. { *************************************************************************
  68.      Compare two strings.
  69. ************************************************************************* }
  70.   procedure CompStr(RecStr, SearchStr : Str255 ; Var Flag : byte ) ;
  71.  
  72.      begin
  73.        if RecStr > SearchStr then 
  74.           Flag := 0
  75.        else
  76.           if SearchStr > RecStr then 
  77.              Flag := 1
  78.           else
  79.              Flag := 2 ;
  80.      end ;
  81.  
  82. { *************************************************************************
  83.      Compare two boolean expressions.
  84. ************************************************************************* }
  85.   procedure CompBoolean(RecStr, SearchStr : Str255 ; Var Flag : byte ) ;
  86.  
  87.      begin
  88.        if RecStr > SearchStr then 
  89.           Flag := 0
  90.        else
  91.           if SearchStr > RecStr then 
  92.              Flag := 1
  93.           else
  94.              Flag := 2 ;
  95.      end ;
  96.  
  97. { *************************************************************************
  98.      Compare two numbers, integer or real.
  99. ************************************************************************* }
  100.   procedure CompNum(RecStr, SearchStr : Str255 ; Var Flag : byte ) ;
  101.  
  102.     var
  103.        RecNum,
  104.        SearchNum : real ;
  105.  
  106.      begin
  107.        CheckNumber(RecStr) ;
  108.        CheckNumber(SearchStr) ;
  109.        ReadV(RecStr, RecNum) ;
  110.        ReadV(SearchStr, SearchNum) ;
  111.  
  112.        if RecNum > SearchNum then 
  113.           Flag := 0
  114.        else
  115.           if RecNum < SearchNum then 
  116.              Flag := 1
  117.           else
  118.              Flag := 2 ;
  119.      end ;
  120.  
  121. { *************************************************************************
  122.      Compare two dates.
  123. ************************************************************************* }
  124.   procedure CompDate(RecStr, SearchStr : Str255 ; Var Flag : byte ) ;
  125.  
  126.     var
  127.        i, j : short_integer ;
  128.        Date : array[1..2,1..3] of short_integer ;
  129.          
  130.      begin
  131.        ConvDate(SearchStr, Date[1,1], Date[1,2], Date[1,3] ) ;
  132.        ConvDate(RecStr, Date[2,1], Date[2,2], Date[2,3] ) ;
  133.  
  134.        for i := 1 to 3 do
  135.            begin
  136.              if Date[1,i] = 0 then
  137.                 Date[1,i] := Date[2,i] ;
  138.             end ;
  139.        if Date[1,3] > Date[2,3] then   { Compare Years }
  140.           Flag := 1
  141.        else
  142.           if Date[1,3] < Date[2,3] then
  143.              Flag := 0
  144.           else
  145.              if Date[1,1] > Date[2,1] then   { Compare Months }
  146.                 Flag := 1
  147.              else
  148.                 if Date[1,1] < Date[2,1] then
  149.                    Flag := 0
  150.                 else
  151.                    if Date[1,2] > Date[2,2] then   { Compare Days }
  152.                       Flag := 1
  153.                    else
  154.                       if Date[1,2] < Date[2,2] then
  155.                          Flag := 0
  156.                       else
  157.                          Flag := 2 ;
  158.      end ;
  159.        
  160. { *************************************************************************
  161.      Compare two dollar amounts.
  162. ************************************************************************* }
  163.   procedure CompDollar(RecStr, SearchStr : Str255 ; Var Flag : byte ) ;
  164.  
  165.     var
  166.        RecNum,
  167.        SearchNum : real ;
  168.  
  169.      begin
  170.        ConvDollar(SearchStr, SearchNum) ;
  171.        ConvDollar(RecStr, RecNum) ;
  172.  
  173.        if RecNum > SearchNum then
  174.           Flag := 0
  175.        else
  176.           if RecNum < SearchNum then
  177.              Flag := 1
  178.           else
  179.              Flag := 2 ;
  180.      end ;
  181.  
  182. { **************************** SEARCH ROUTINES ************************** }
  183. { *************************************************************************
  184.      Prepare names by removing extra spaces and calling LastNameFirst
  185.      of necessary.
  186. ************************************************************************* }
  187.   procedure PrepName(ScrRec : ScrPtr ; CurRec, SearchRec : DataPtr ; 
  188.                      Flag : boolean ; Var RecStr, SearchStr : Str255 ) ;
  189.  
  190.     var
  191.        SpacePos : short_integer ;
  192.        BoolChar : StrChar ;
  193.    
  194.      begin
  195.        if Flag then
  196.           begin
  197.             LastNameFirst(RecStr) ;
  198.             SpacePos := Pos(' ', RecStr) ;
  199.             if SpacePos > 0 then
  200.                Delete(RecStr, SpacePos, Length(RecStr) - SpacePos + 1) ;
  201.           end
  202.        else
  203.           begin
  204.             GetChar(ScrRec^.Next, CurRec, BoolChar, 
  205.                     ScrRec^.Next^.Offset) ;
  206.             if BoolChar <> 'T' then
  207.                LastNameFirst(RecStr) ;
  208.                     
  209.             GetChar(ScrRec^.Next, SearchRec, BoolChar, 
  210.                     ScrRec^.Next^.Offset) ;
  211.             if BoolChar <> 'T' then
  212.                LastNameFirst(SearchStr) ;
  213.          end ;
  214.      end ;
  215.  
  216. { *************************************************************************
  217.      Check for astericks at beginning and end of a search string.
  218.      The asterick is the wildcard designator for searchs.
  219. ************************************************************************* }
  220.   procedure AsterikChk(Var SearchStr : Str255 ; 
  221.                        Var StarPos1, StarPos2 : boolean) ;
  222.  
  223.      var
  224.         Asterik : short_integer ;
  225.  
  226.       begin
  227.         if SearchStr[1] = chr($2A) then 
  228.            StarPos1 := true
  229.         else
  230.            StarPos1 := false ;
  231.             
  232.         if SearchStr[Length(SearchStr)] = chr($2A) then 
  233.            StarPos2 := true
  234.         else
  235.            StarPos2 := false ;
  236.  
  237.         Asterik := 1 ;
  238.         While Asterik > 0 do
  239.            begin
  240.              Asterik := Pos(chr($2A), SearchStr) ;
  241.              if Asterik > 0 then
  242.                 Delete(SearchStr,Asterik,1) ;
  243.            end ;
  244.       end ;            
  245.       
  246. { *************************************************************************
  247.      Select correct comparison routine depending upon DataType.
  248. ************************************************************************* }
  249.   procedure Do_Comparison( ScrRec : ScrPtr ; CurRec, SearchRec : DataPtr ;
  250.                            StarPos1, StarPos2 : boolean ;
  251.                            RecStr, SearchStr : Str255 ; 
  252.                           Var Flag : byte) ;
  253.  
  254.     var
  255.        Character : StrChar ;
  256.        CharInt   : short_integer ;
  257.  
  258.      begin
  259.        Character := ScrRec^.DataType ;
  260.        GetAscii(Character, CharInt ) ;
  261.        if StarPos2 AND (CharInt = $48) then
  262.           CharInt := $41 ;
  263.  
  264.        Case CharInt of
  265.            $41 : CompStr(RecStr, SearchStr, Flag) ;
  266.            $42 : CompBoolean(RecStr, SearchStr, Flag) ;
  267.            $43,
  268.            $44,
  269.            $45 : CompNum(RecStr, SearchStr, Flag) ;
  270.            $46 : CompDollar(RecStr, SearchStr, Flag) ;
  271.            $47 : CompDate(RecStr, SearchStr, Flag) ;
  272.            $48 : begin
  273.                    PrepName(ScrRec, CurRec, SearchRec, 
  274.                             StarPos1, RecStr, SearchStr) ;
  275.                    CompStr(RecStr, SearchStr, Flag) ;
  276.                  end ;
  277.        end ;
  278.      end ;
  279.  
  280. { *************************************************************************
  281.      Check equality of two records.
  282. ************************************************************************* }
  283.   procedure ChkEqual(    ScrRec : ScrPtr ; CurRec, SearchRec : DataPtr ;
  284.                          SearchStr, RecStr : Str255 ;
  285.                      Var Match : boolean ) ;
  286.  
  287.     var
  288.        StarPos : array[1..2] of boolean ;
  289.        Flag    : byte ;
  290.  
  291.      begin
  292.        if ScrRec^.DataType <> 'G' then
  293.           AsterikChk(SearchStr, StarPos[1], StarPos[2]) ;
  294.  
  295.        if  (ScrRec^.DataType = 'A') OR
  296.           ((ScrRec^.DataType = 'H') AND (StarPos[2])) then
  297.           begin
  298.             Match := true ;
  299.               
  300.             if NOT StarPos[1] AND NOT StarPos[2] then
  301.                begin
  302.                  if SearchStr <> RecStr then
  303.                     Match := false ;
  304.                end
  305.             else
  306.                if StarPos[1] AND NOT StarPos[2] then
  307.                   begin
  308.                     if Pos(SearchStr, RecStr) <> 
  309.                            Length(RecStr) - Length(SearchStr) + 1 then
  310.                        Match := false ;
  311.                   end
  312.                else
  313.                   if NOT StarPos[1] AND StarPos[2] then
  314.                      begin
  315.                        if Pos(SearchStr, RecStr) <> 1 then
  316.                           Match := false ;
  317.                      end
  318.                   else
  319.                      if Pos(SearchStr, RecStr) = 0 then
  320.                         Match := false ;
  321.           end
  322.        else
  323.           begin
  324.             Do_Comparison( ScrRec, CurRec, SearchRec,
  325.                            StarPos[1],StarPos[2], RecStr, SearchStr, Flag ) ;
  326.             if Flag = 2 then
  327.                Match := true
  328.             else
  329.                Match := false ;
  330.           end ;
  331.       end ;
  332.  
  333. { *************************************************************************
  334.      Check if Record value is larger than Search value.
  335. ************************************************************************* }
  336.   procedure ChkGreater(    ScrRec : ScrPtr ; CurRec, SearchRec : DataPtr ;
  337.                            SearchStr, RecStr : Str255 ;
  338.                        Var Match : boolean ) ;
  339.  
  340.     var
  341.        StarPos  : array[1..2] of boolean ;
  342.        Flag     : byte ;
  343.  
  344.      begin
  345.        if ScrRec^.DataType <> 'G' then
  346.           AsterikChk(SearchStr, StarPos[1], StarPos[2]) ;
  347.     
  348.        Do_Comparison(ScrRec, CurRec, SearchRec, 
  349.                      StarPos[1],StarPos[2], RecStr, SearchStr, Flag ) ;
  350.  
  351.        if Flag = 0 then
  352.           Match := true
  353.        else
  354.           Match := false ;
  355.      end ;
  356.      
  357. { *************************************************************************
  358.      Check if Record value is less than Search value.
  359. ************************************************************************* }
  360.   procedure ChkLess(    ScrRec : ScrPtr ; CurRec, SearchRec : DataPtr ;
  361.                         SearchStr, RecStr : Str255 ;
  362.                     Var Match : boolean ) ;
  363.  
  364.     var
  365.        StarPos : array[1..2] of boolean ;
  366.        Flag    : byte ;
  367.  
  368.      begin
  369.        if ScrRec^.DataType <> 'G' then
  370.           AsterikChk(SearchStr, StarPos[1], StarPos[2]) ;
  371.            
  372.        Do_Comparison(ScrRec, CurRec, SearchRec,
  373.                      StarPos[1],StarPos[2], RecStr, SearchStr, Flag ) ;
  374.  
  375.        if Flag = 1 then
  376.           Match := true
  377.        else
  378.           Match := false ;
  379.      end ;
  380.  
  381. { *************************************************************************
  382.      Check if Record is not equal to Search value.
  383. ************************************************************************* }
  384.   procedure ChkNotEqual(  ScrRec : ScrPtr ; CurRec, SearchRec : DataPtr ;
  385.                           SearchStr, RecStr : Str255 ;
  386.                         Var Match : boolean ) ;
  387.  
  388.     var
  389.        NotEqual : array[1..2] of boolean ;
  390.                            
  391.      begin
  392.        NotEqual[1] := true ;
  393.        NotEqual[2] := true ;
  394.        ChkGreater(ScrRec, CurRec, SearchRec, SearchStr, RecStr, NotEqual[1] ) ;
  395.        ChkLess(ScrRec, CurRec, SearchRec, SearchStr, RecStr, NotEqual[2] ) ;
  396.  
  397.        if NotEqual[1] OR NotEqual[2] then 
  398.           Match := true
  399.        else 
  400.           Match := false ;
  401.      end ;
  402.      
  403. { *************************************************************************
  404.      Check if Record is less than or equal to Search Value.
  405. ************************************************************************* }
  406.   procedure ChkLessEqual(  ScrRec : ScrPtr ; CurRec, SearchRec : DataPtr ;
  407.                            SearchStr, RecStr : Str255 ;
  408.                          Var Match : boolean ) ;
  409.  
  410.     var
  411.        NotEqual : array[1..2] of boolean ;
  412.                             
  413.      begin
  414.        NotEqual[1] := true ;
  415.        NotEqual[2] := true ;
  416.        ChkLess(ScrRec, CurRec, SearchRec, SearchStr, RecStr, NotEqual[1] ) ;
  417.        ChkEqual(ScrRec, CurRec, SearchRec, SearchStr, RecStr, NotEqual[2] ) ;
  418.  
  419.        if NotEqual[1] OR NotEqual[2] then 
  420.           Match := true
  421.        else 
  422.           Match := false ;
  423.      end ;
  424.  
  425. { *************************************************************************
  426.      Check if Record is greater than or equal to Search Value.
  427. ************************************************************************* }
  428.   procedure ChkGreatEqual( ScrRec : ScrPtr ; CurRec, SearchRec : DataPtr ;
  429.                            SearchStr, RecStr : Str255 ;
  430.                           Var Match : boolean ) ;
  431.  
  432.     var
  433.        NotEqual : array[1..2] of boolean ;
  434.                             
  435.      begin
  436.        NotEqual[1] := true ;
  437.        NotEqual[2] := true ;
  438.        ChkGreater(ScrRec, CurRec, SearchRec, SearchStr, RecStr, NotEqual[1] ) ;
  439.        ChkEqual(ScrRec, CurRec, SearchRec, SearchStr, RecStr, NotEqual[2] ) ;
  440.  
  441.        if NotEqual[1] OR NotEqual[2] then 
  442.           Match := true
  443.        else 
  444.           Match := false ;
  445.      end ;
  446.  
  447. { *************************************************************************
  448.      Search the data base.
  449. ************************************************************************* }
  450.   procedure SearchDataBase(Var NewMode : short_integer ) ;
  451.  
  452.     var
  453.        InputStr: Str255 ;
  454.        i,
  455.        Counter : short_integer ;
  456.        RecStr  : array[1..2] of Str255 ;
  457.        ScrRec  : ScrPtr ;
  458.        CurRec,
  459.        SearchRec : DataPtr ;
  460.        Match,
  461.        CompareFlag : boolean ;
  462.  
  463.      begin
  464.        CurRec := D_FirstRec[DataNum] ;
  465.        Counter := 1 ;
  466.        SearchRec := D_LastRec[DataNum] ;
  467.        While CurRec <> D_LastRec[DataNum] do
  468.           begin
  469.             ScrRec := S_FirstRec[ScrNum] ;
  470.             C_CurRec := C_FirstRec ;
  471.             Match := true ;
  472.             While ScrRec <> nil do
  473.                begin
  474.                  GetStr(SearchRec, RecStr[1], 
  475.                         ScrRec^.Offset, ScrRec^.Size) ;
  476.                  CompareFlag := false ;
  477.                  if ScrRec^.DataType = 'F' then
  478.                     begin
  479.                       if Length(RecStr[1]) > 1 then
  480.                          CompareFlag := true ;
  481.                     end
  482.                  else
  483.                     if Length(RecStr[1]) > 0 then
  484.                        CompareFlag := true ;
  485.                  if CompareFlag then
  486.                     begin
  487.                       GetStr(CurRec, RecStr[2], ScrRec^.Offset, 
  488.                              ScrRec^.Size) ;
  489.                       Case C_CurRec^.Match of
  490.                               { MemRec  =  SearchRec }
  491.                           1 : ChkEqual(ScrRec, CurRec, SearchRec,
  492.                                        RecStr[1], RecStr[2], Match) ;
  493.                               { MemRec  >  SearchRec }
  494.                           2 : ChkGreater(ScrRec, CurRec, SearchRec,
  495.                                          RecStr[1], RecStr[2], Match ) ;
  496.                               { MemRec  <  SearchRec }
  497.                           3 : ChkLess(ScrRec, CurRec, SearchRec,
  498.                                       RecStr[1], RecStr[2], Match ) ;
  499.                               { MemRec  <>  SearchRec }
  500.                           4 : ChkNotEqual(ScrRec, CurRec, SearchRec,
  501.                                           RecStr[1], RecStr[2], Match ) ;
  502.                               { MemRec  <=  SearchRec }
  503.                           5 : ChkLessEqual(ScrRec, CurRec, SearchRec,
  504.                                            RecStr[1], RecStr[2], Match ) ;
  505.                               { MemRec  >=  SearchRec }
  506.                           6 : ChkGreatEqual(ScrRec, CurRec, SearchRec,
  507.                                             RecStr[1], RecStr[2], Match ) ;
  508.                       end ;
  509.                     end ;
  510.                  if Match then
  511.                     begin
  512.                       ScrRec := ScrRec^.Next ;
  513.                       C_CurRec := C_CurRec^.Next ;
  514.                     end
  515.                  else
  516.                     ScrRec := nil ;
  517.                end ;
  518.             if Match then
  519.                Int_AddARec(F_FirstRec,F_CurRec,F_LastRec, Counter) ;
  520.             Counter := Counter + 1 ;
  521.             CurRec := CurRec^.Next ;
  522.           end ;
  523.  
  524.        Mode := 2 ;
  525.        DS_DeleteARec(D_LastRec[DataNum]) ;
  526.        Mode := 3 ;
  527.        D_CurrentRec[DataNum] := D_FirstRec[DataNum] ;
  528.        if F_FirstRec <> nil then
  529.           begin
  530.             F_CurRec := F_FirstRec ;
  531.             F_RecNo[DataNum] := 1 ;
  532.             for i := 2 to F_CurRec^.Match do
  533.                 D_CurrentRec[DataNum] := 
  534.                              D_CurrentRec[DataNum]^.Next ;
  535.             RecNo[DataNum] := i - 1 ;
  536.           end
  537.        else
  538.           begin
  539.             NewMode := 2 ;
  540.             RecNo[DataNum] := 1 ;
  541.             AlertStr := '[2][  |No Records Match|]' ;
  542.             AlertStr := Concat(AlertStr, '[ Continue ]') ;
  543.             Result   := Do_Alert(AlertStr,1) ;
  544.           end ;
  545.             
  546.        F_CurRec := F_FirstRec ;
  547.        F_TotalRec[DataNum] := 0 ;
  548.        While F_CurRec <> nil do
  549.           begin
  550.             F_TotalRec[DataNum] := F_TotalRec[DataNum] + 1 ;
  551.             F_CurRec := F_CurRec^.Next ;
  552.           end ;
  553.        F_CurRec := F_FirstRec ;
  554.        F_RecNo[DataNum] := 1 ;
  555.      end ;
  556.  
  557. { *************************  SORTING ROUTINES  *************************** }
  558. { *************************************************************************
  559.      Compare records for sort.
  560. ************************************************************************* }
  561.   procedure Compare( ScrRec : ScrPtr ; CurRec, SearchRec : DataPtr ;
  562.                     Var Flag : byte) ;
  563.  
  564.     var
  565.        i         : short_integer ;
  566.        RecStr,
  567.        SearchStr : Str255 ;
  568.        Character : StrChar ;
  569.        CharInt   : short_integer ;
  570.        BoolChar  : StrChar ;
  571.                          
  572.      begin
  573.        GetStr(CurRec, RecStr, ScrRec^.Offset, ScrRec^.Size) ;
  574.        GetStr(SearchRec, SearchStr, ScrRec^.Offset, ScrRec^.Size) ;
  575.        if ScrRec^.DataType = 'H' then
  576.           begin
  577.             GetChar(ScrRec^.Next, CurRec, BoolChar, ScrRec^.Next^.Offset) ;
  578.             if BoolChar <> 'T' then
  579.                LastNameFirst(RecStr) ;
  580.             GetChar(ScrRec^.Next, SearchRec, BoolChar, ScrRec^.Next^.Offset) ;
  581.             if BoolChar <> 'T' then
  582.                LastNameFirst(SearchStr) ;
  583.           end ;
  584.  
  585.        Character := ScrRec^.DataType ;
  586.        GetAscii(Character, CharInt ) ;
  587.  
  588.        Case CharInt of
  589.            $41, 
  590.            $48 : CompStr(RecStr, SearchStr, Flag) ;
  591.            $42 : CompBoolean(RecStr, SearchStr, Flag) ;
  592.            $43,
  593.            $44,
  594.            $45 : CompNum(RecStr, SearchStr, Flag) ;
  595.            $46 : CompDollar(RecStr, SearchStr, Flag) ;
  596.            $47 : CompDate(RecStr, SearchStr, Flag) ;
  597.        end ;
  598.      end ;
  599.  
  600. { *************************************************************************
  601.      Sort Records Subroutine.
  602. ************************************************************************* }
  603.   procedure QuickSort(    Start, Finish : short_integer ; 
  604.                       Var TempRec, CheckRec : DataPtr ; ScrRec : ScrPtr ;
  605.                           Ascend : boolean) ;
  606.   
  607.     var
  608.        i,
  609.        StartValue,
  610.        Left,
  611.        Right      : short_integer ;
  612.        LeftRec,
  613.        RightRec,
  614.        StartRec   : DataPtr ;
  615.        LeftStr,
  616.        RightStr,
  617.        StartStr   : Str255 ;
  618.        Flag       : byte ;
  619.  
  620.      procedure DecRec(Var Index : short_integer ;
  621.                       Var CurStr : Str255 ; 
  622.                       Var CurRec : DataPtr ;
  623.                           ScrRec : ScrPtr ) ;
  624.  
  625.         begin
  626.           Index := Index - 1 ;
  627.           if CurRec <> nil then
  628.              CurRec := CurRec^.Prev ;
  629.         end ;
  630.  
  631.      procedure IncRec(Var Index : short_integer ;
  632.                       Var CurStr : Str255 ; 
  633.                       Var CurRec : DataPtr ;
  634.                           ScrRec : ScrPtr ) ;
  635.  
  636.         begin
  637.           Index := Index + 1 ;
  638.           if CurRec <> nil then
  639.              CurRec := CurRec^.Next ;
  640.         end ;
  641.  
  642.      procedure SortNextLevel(    FirstRec, SecondRec : DataPtr ;
  643.                              Var Flag : byte ) ;
  644.      
  645.        Var
  646.           i        : short_integer ;
  647.           NextRec  : ScrPtr ;
  648.           ExitFlag : boolean ;
  649.           Ascend   : array[1..2] of boolean ;
  650.      
  651.         begin
  652.           ExitFlag := false ;
  653.           repeat 
  654.             if F_CurRec^.Next <> nil then
  655.                begin
  656.                  C_CurRec := C_CurRec^.Next ;
  657.                  if C_FirstRec^.Match = 1 then
  658.                     Ascend[1] := true
  659.                  else
  660.                     Ascend[1] := false ;
  661.                  if C_CurRec^.Match = 1 then
  662.                     Ascend[2] := true
  663.                  else
  664.                     Ascend[2] := false ;
  665.                  NextRec := S_FirstRec[ScrNum] ;
  666.                  F_CurRec := F_CurRec^.Next ;
  667.                  for i := 2 to F_CurRec^.Match do
  668.                      NextRec := NextRec^.Next ;
  669.                  Compare(NextRec, FirstRec, SecondRec, Flag) ;
  670.                  if Flag <> 2 then
  671.                     begin
  672.                       if Ascend[1] <> Ascend[2] then
  673.                          begin
  674.                            if Flag = 1 then
  675.                               Flag := 0
  676.                            else
  677.                               if Flag = 0 then
  678.                                  Flag := 1 ;
  679.                          end ;
  680.                       ExitFlag := true ;
  681.                     end ;
  682.                end 
  683.             else
  684.                begin
  685.                  Flag := 2 ;
  686.                  ExitFlag := true ;
  687.                end ;
  688.           until ExitFlag ;
  689.           F_CurRec := F_FirstRec ;
  690.           C_CurRec := C_FirstRec ;
  691.         end ;
  692.  
  693.  
  694.      begin
  695.        Left := Start ;
  696.        LeftRec := D_FirstRec[DataNum] ;
  697.        for i := 2 to Left do
  698.            LeftRec := LeftRec^.Next ;
  699.  
  700.        Right := Finish ;
  701.        RightRec := D_FirstRec[DataNum] ;
  702.        for i := 2 to Right do
  703.            RightRec := RightRec^.Next ;
  704.  
  705.        StartValue := (Start + Finish) DIV 2 ;
  706.        StartRec := D_FirstRec[DataNum] ;
  707.        for i := 2 to StartValue do
  708.            StartRec := StartRec^.Next ;
  709.        CheckRec^ := StartRec^ ;
  710.  
  711.        repeat
  712.          Compare(ScrRec, LeftRec, CheckRec, Flag) ;
  713.          if (Flag = 2) AND (LeftRec <> CheckRec) then
  714.             SortNextLevel(LeftRec, CheckRec, Flag) ;
  715.          while ((Flag = 1) AND Ascend) OR
  716.                ((Flag = 0) AND NOT Ascend) do
  717.             begin
  718.               Left := Left + 1 ;
  719.               LeftRec := LeftRec^.Next ;
  720.               Compare(ScrRec, LeftRec, CheckRec, Flag) ;
  721.               if (Flag = 2) AND (LeftRec <> CheckRec) then
  722.                  SortNextLevel(LeftRec, CheckRec, Flag) ;
  723.             end ;
  724.  
  725.          Compare(ScrRec, CheckRec, RightRec, Flag) ;
  726.          if (Flag = 2) AND (CheckRec <> RightRec) then
  727.             SortNextLevel(CheckRec, RightRec, Flag) ;
  728.          while ((Flag = 1) AND Ascend) OR
  729.                ((Flag = 0) AND NOT Ascend) do
  730.             begin
  731.               Right := Right - 1 ;
  732.               RightRec := RightRec^.Prev ;
  733.               Compare(ScrRec, CheckRec, RightRec, Flag) ;
  734.               if (Flag = 2) AND (CheckRec <> RightRec) then
  735.                  SortNextLevel(CheckRec, RightRec, Flag) ;
  736.             end ;
  737.  
  738.          if Left <= Right then 
  739.             begin
  740.               TempRec^.Data  := LeftRec^.Data ;
  741.               LeftRec^.Data  := RightRec^.Data ;
  742.               RightRec^.Data := TempRec^.Data ;
  743.               IncRec(Left, LeftStr, LeftRec, ScrRec) ;
  744.               DecRec(Right, RightStr, RightRec, ScrRec) ;
  745.             end ; 
  746.        until Right <= Left ;
  747.  
  748.        if Start < Right then QuickSort(Start, Right, TempRec, CheckRec,
  749.                                        ScrRec, Ascend) ;
  750.        if Left < Finish then QuickSort(Left, Finish, TempRec, CheckRec,
  751.                                        ScrRec, Ascend) ;
  752.      end ;
  753.  
  754.  
  755.   procedure SortRecords(CurRec : DataPtr ; Var NewMode : short_integer ) ;
  756.  
  757.     var
  758.       i : short_integer ;
  759.       TempRec,
  760.       CheckRec: DataPtr ;
  761.       ScrRec  : ScrPtr ;
  762.       Ascend  : boolean ;
  763.       Value   : short_integer ;
  764.       CurChar : StrChar ;
  765.  
  766.      begin
  767.        F_CurRec := F_FirstRec ;
  768.        while F_CurRec <> nil do
  769.          begin
  770.            ScrRec := S_FirstRec[ScrNum] ;
  771.            for i := 2 to F_CurRec^.Match do
  772.                ScrRec := ScrRec^.Next ;
  773.            GetChar(ScrRec, D_LastRec[DataNum], CurChar, ScrRec^.Offset) ;
  774.            
  775.            if CurChar = chr(3) then
  776.               Value := 1
  777.            else
  778.               Value := 0 ;
  779.            Int_AddARec(C_FirstRec, C_CurRec, C_LastRec, Value ) ;
  780.            F_CurRec := F_CurRec^.Next ;
  781.          end ;
  782.        
  783.        C_CurRec := C_FirstRec ;
  784.        F_CurRec := F_FirstRec ;
  785.        ScrRec := S_FirstRec[ScrNum] ;
  786.        for i := 2 to F_CurRec^.Match do
  787.            ScrRec := ScrRec^.Next ;
  788.        
  789.        if C_CurRec^.Match = 1 then
  790.           Ascend := true
  791.        else
  792.           Ascend := false ;
  793.  
  794.        DS_DeleteARec(D_LastRec[DataNum]) ;
  795.  
  796.        new(TempRec) ;
  797.        new(CheckRec) ;
  798.        QuickSort(1, TotalRec[DataNum], TempRec, CheckRec, ScrRec, Ascend) ;
  799.        RecNo[DataNum] := 1 ;
  800.        D_CurrentRec[DataNum] := D_FirstRec[DataNum] ;
  801.        NewMode := 2 ;
  802.      end ;
  803.  
  804. BEGIN
  805. END .
  806.  
  807.